package com.etooling.pdm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.etooling.framework.entity.Employee;
import com.etooling.framework.repository.EmployeeRepository;
import com.etooling.framework.svo.ReplyObj;
import com.etooling.framework.utils.WebUtils;
import com.etooling.pdm.dto.GoodsSpecsDTO;
import com.etooling.pdm.entity.GoodsSpecs;
import com.etooling.pdm.entity.GoodsSpecsStockRecord;
import com.etooling.pdm.mapper.PdmMapper;
import com.etooling.pdm.repository.GoodsSpecsRepository;
import com.etooling.pdm.repository.GoodsSpecsStockRecordRepository;
import com.etooling.pdm.service.GoodsSpecsStockRecordService;
import com.etooling.pdm.vo.GoodsSpecsStockRecordVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;
import java.util.Optional;

/**
 * @author dyz
 * @date 2023/4/4 13:43
 * @description GoodsServiceImpl
 */
@Service
public class GoodsSpecsStockRecordServiceImpl implements GoodsSpecsStockRecordService {

    @Autowired
    private GoodsSpecsStockRecordRepository stockRepository;
    @Autowired
    private GoodsSpecsStockRecordRepository stockRecordRepository;
    @Autowired
    private GoodsSpecsRepository goodsSpecsRepository;
    @Autowired
    private EmployeeRepository employeeRepository;
    @Autowired
    private PdmMapper pdmMapper;

    @Override
    @Transactional
    public ReplyObj operateStock(HttpServletRequest request, String goodsSpecsId, Integer quantity, String operationType, String stockType, String memo) {
        // 使用悲观锁锁定物料记录
        GoodsSpecs goodsSpecs = goodsSpecsRepository.findByIdWithLock(goodsSpecsId).orElse(null);
        if (goodsSpecs == null) {
            return WebUtils.flushFailure("物料不存在");
        }
        String companyId = (String) WebUtils.getSessionValue(request, WebUtils.LOGIN_COMPANY_ID_KEY);
        String userId = (String) WebUtils.getSessionValue(request, WebUtils.LOGIN_USER_KEY);

        Employee operator = employeeRepository.findById(userId).orElse(null);
        if (operator == null) {
            return WebUtils.flushFailure("操作人不存在");
        }

        // 创建出入库记录
        GoodsSpecsStockRecord record = new GoodsSpecsStockRecord();
        record.setGoodsSpecs(goodsSpecs);
        record.setOperator(operator);
        record.setCompanyId(companyId);

        record.setOperationType(operationType);
        record.setStockNum(quantity);
        record.setStockType(stockType);
        record.setRecordTime(new Date());
        record.setMemo(memo);

        record.setStatus(GoodsSpecsStockRecord.STATUS_NORMAL);

        stockRecordRepository.save(record);

        // 更新物料库存
        // 避免库存为负数或者不是可以计算的数据
        if (goodsSpecs.getStock() == null) {
            goodsSpecs.setStock(0);
        }
        if (GoodsSpecsStockRecord.OPERATION_TYPE_IN.equals(operationType)) {
            goodsSpecs.setStock(goodsSpecs.getStock() + quantity);
        } else if (GoodsSpecsStockRecord.OPERATION_TYPE_OUT.equals(operationType)) {
            goodsSpecs.setStock(goodsSpecs.getStock() - quantity);
        }
        if (goodsSpecs.getStock() < 0) {
            return WebUtils.flushFailure("库存不足");
        }
        goodsSpecs.setStockUpdateDate(new Date());
        goodsSpecsRepository.save(goodsSpecs);

        return WebUtils.flushSuccess("操作成功");
    }

    @Override
    @Transactional
    public ReplyObj revokeStockRecord(HttpServletRequest request, String recordId, String revokeReason) {
        Optional<GoodsSpecsStockRecord> recordOpt = stockRecordRepository.findById(recordId);
        if (!recordOpt.isPresent()) {
            return WebUtils.flushFailure("记录不存在");
        }

        GoodsSpecsStockRecord record = recordOpt.get();
        Date now = new Date();
        long timeDiff = now.getTime() - record.getRecordTime().getTime();
        if (timeDiff > 30 * 60 * 1000) { // 30分钟
            return WebUtils.flushFailure("超过可撤回时间");
        }

        // 更新记录状态
        String userId = (String) WebUtils.getSessionValue(request, WebUtils.LOGIN_USER_KEY);
        record.setRevokeBy(userId);
        record.setStatus(GoodsSpecsStockRecord.STATUS_REVOKED);
        record.setRevokeTime(now);
        record.setRevokeReason(revokeReason);
        stockRecordRepository.save(record);

        // 调整库存
        GoodsSpecs goodsSpecs = record.getGoodsSpecs();
        if (GoodsSpecsStockRecord.OPERATION_TYPE_IN.equals(record.getOperationType())) {
            goodsSpecs.setStock(goodsSpecs.getStock() - record.getStockNum());
        } else if (GoodsSpecsStockRecord.OPERATION_TYPE_OUT.equals(record.getOperationType())) {
            goodsSpecs.setStock(goodsSpecs.getStock() + record.getStockNum());
        }
        goodsSpecsRepository.save(goodsSpecs);

        return WebUtils.flushSuccess("撤回成功");
    }

    @Override
    public ReplyObj pageQueryStockRecords(
            HttpServletRequest request,
            Boolean isAll,
            String operationType,
            String goodsSpecsId,
            String status,
            String orderBy,
            Boolean orderType,
            Integer pageNum,
            Integer pageSize) {
        String companyId = (String) WebUtils.getSessionValue(request, WebUtils.LOGIN_COMPANY_ID_KEY);
        String userId = (String) WebUtils.getSessionValue(request, WebUtils.LOGIN_USER_KEY);

        QueryWrapper<Map<String, Object>> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("companyId", companyId);
        if (isAll == null || !isAll) {
            queryWrapper.eq("operatorId", userId);
        }
        if (WebUtils.checkStr(operationType)) {
            queryWrapper.eq("operationType", operationType);
        }
        if (WebUtils.checkStr(goodsSpecsId)) {
            queryWrapper.eq("goodsSpecsId", goodsSpecsId);
        }
        if (WebUtils.checkStr(status)) {
            queryWrapper.eq("status", status);
        }
        if (WebUtils.checkStr(orderBy)) {
            if (orderType != null && orderType) {
                queryWrapper.orderByAsc(orderBy);
            } else {
                queryWrapper.orderByDesc(orderBy);
            }
        }

        // 分页数据
        Page<Map<String, Object>> returnPage = new Page<>(pageNum, pageSize);
        IPage<Map<String, Object>> iPage = pdmMapper.pageQueryStockRecords(queryWrapper, returnPage);

        return WebUtils.flushSuccess(iPage);
    }
}
